extends Resource
class_name Ability

enum AbilityType { ACTIVE, PASSIVE }
enum TargetType { SELF, SINGLE_ENEMY, AOE_ENEMY, SINGLE_ALLY, AOE_ALLY }

@export var ability_name: String = "Basic Ability"
@export var ability_type: AbilityType = AbilityType.ACTIVE
@export var target_type: TargetType = TargetType.SINGLE_ENEMY
@export var cooldown: float = 5.0
@export var mana_cost: int = 50
@export var damage: float = 0.0
@export var heal: float = 0.0
@export var duration: float = 0.0
@export var radius: float = 3.0
@export var description: String = ""

var current_cooldown: float = 0.0
var is_ready: bool = false

func use_ability(caster: Node3D, targets: Array) -> bool:
	if not is_ready and ability_type == AbilityType.ACTIVE:
		return false
	
	match ability_name:
		"Shield Bash":
			shield_bash(caster, targets)
		"Rapid Fire":
			rapid_fire(caster, targets)
		"Fireball":
			fireball(caster, targets)
		"Shadow Strike":
			shadow_strike(caster, targets)
		"Healing Wave":
			healing_wave(caster, targets)
		_:
			basic_ability(caster, targets)
	
	if ability_type == AbilityType.ACTIVE:
		current_cooldown = cooldown
		is_ready = false
	
	return true

func update_cooldown(delta: float):
	if current_cooldown > 0:
		current_cooldown -= delta
		if current_cooldown <= 0:
			is_ready = true

func shield_bash(caster: Node3D, targets: Array):
	if targets.size() > 0:
		var target = targets[0]
		if target.has_method("take_damage"):
			target.take_damage(damage * 1.5)
		if target.has_method("apply_stun"):
			target.apply_stun(1.5)

func rapid_fire(caster: Node3D, targets: Array):
	if caster.has_method("add_attack_speed"):
		caster.add_attack_speed(1.0)
	if caster.has_method("create_timer"):
		await caster.create_timer(3.0)
		if caster.has_method("add_attack_speed"):
			caster.add_attack_speed(-1.0)

func fireball(caster: Node3D, targets: Array):
	for target in targets:
		if target.has_method("take_damage"):
			var distance = caster.global_position.distance_to(target.global_position)
			if distance <= radius:
				target.take_damage(damage)

func shadow_strike(caster: Node3D, targets: Array):
	if targets.size() > 0:
		var target = find_lowest_health_enemy(targets)
		if target:
			caster.global_position = target.global_position - (target.global_position - caster.global_position).normalized() * 2
			if target.has_method("take_damage"):
				target.take_damage(damage * 2.0)

func healing_wave(caster: Node3D, targets: Array):
	var allies = caster.get_tree().get_nodes_in_group("player_units" if caster.is_player_unit else "enemy_units")
	allies.sort_custom(func(a, b): return a.current_health < b.current_health)
	
	for i in range(min(3, allies.size())):
		if allies[i].has_method("heal"):
			allies[i].heal(heal)

func basic_ability(caster: Node3D, targets: Array):
	if targets.size() > 0 and damage > 0:
		var target = targets[0]
		if target.has_method("take_damage"):
			target.take_damage(damage)

func find_lowest_health_enemy(enemies: Array) -> Node3D:
	var lowest = null
	var min_health = INF
	
	for enemy in enemies:
		if enemy.has_method("get_health_percentage"):
			var health_percent = enemy.get_health_percentage()
			if health_percent < min_health:
				min_health = health_percent
				lowest = enemy
	
	return lowest